package ws.jdbc.concurrent.driver.sqlserver;

import java.util.concurrent.locks.ReentrantLock;
import java.io.InputStream;
import java.io.Reader;
import java.math.BigDecimal;
import java.net.URL;
import java.sql.*;
import java.util.Calendar;
import java.util.Map;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
import ws.jdbc.concurrent.driver.sqlserver.tds.ITDSResultSet;
import ws.jdbc.concurrent.driver.sqlserver.tds.TDSMessage;
import ws.jdbc.concurrent.driver.sqlserver.tds.rpc.UpdateValue;
import static ws.jdbc.concurrent.driver.sqlserver.tds.rpc.StoredProcedures.*;

/**
 * Abstract implementation of the {@link ResultSet} interface.
 *
 * This class goal is to provide the general functionality of a result set.
 * 
 * @author Wilson Santos, 36228 <wilson.santos@ua.pt>
 */
public abstract class CResultSet implements ResultSet {

  /** The current row is pointing to before the result set. */
  protected static final int ROW_BEFORE = 0;
  /** The current row is pointing to after the result set. */
  protected static final int ROW_AFTER = -1;
  /** The current row is on the insert row. */
  protected static final int ROW_INSERT = -2;
  /** Channel to communicate with the SQL Server. */
  protected TDSMessage message;
  /** Result set meta-data and row data. It operates as a cache for the rows. */
  protected ITDSResultSet tdsResultSet;
  /** Statement that created this result set. */
  protected final Statement stmt;
  /** Current row number. */
  protected int currentRow;
  /** Last row number. */
  protected final AtomicInteger lastRow;
  /** Save the current row value when moving to insert row. */
  protected int rowBackup;
  /** Cache index. */
  protected int rsIndex;
  /** The last column read had a value of SQL {@code NULL}. */
  protected boolean wasNull;
  /** Number of rows that should be fetched from the database when more rows are needed. */
  protected int fetchSize;
  /** Direction in which this result set will be processed. */
  protected int fetchDirection;
  /** First row in the cache. */
  protected int cacheBegining;
  /** Last row in the cache. */
  protected int cacheEnd;
  /** List with the update values for the current row, or insert values. */
  protected UpdateValue[] updateValues;
  /** Lock used to restrict access to the tds result set or the tds communication channel. */
  protected ReentrantLock lock;
  /** Index of the last column retrieved. It is used for wasNull(). */
  protected int lastColumnIndex;
  /** List with the number of deleted rows. */
  protected final PriorityBlockingQueue<Integer> deletedRows;

  protected CResultSet(final TDSMessage message, final Statement stmt) throws SQLException {
    assert message != null && stmt != null;

    this.message = message;
    this.stmt = stmt;

    this.currentRow = ROW_BEFORE;
    this.rsIndex = -1;
    this.wasNull = false;

    this.fetchSize = stmt.getFetchSize();
    this.fetchDirection = ResultSet.FETCH_FORWARD;

    this.lastRow = new AtomicInteger(0);
    this.deletedRows = new PriorityBlockingQueue<Integer>();
  }

  protected CResultSet(final TDSMessage message, final Statement stmt, final AtomicInteger lastRow) throws SQLException {
    assert message != null && stmt != null;

    this.message = message;
    this.stmt = stmt;

    this.currentRow = ROW_BEFORE;
    this.rsIndex = -1;
    this.wasNull = false;

    this.fetchSize = stmt.getFetchSize();
    this.fetchDirection = ResultSet.FETCH_FORWARD;

    this.lastRow = lastRow;
    this.deletedRows = new PriorityBlockingQueue<Integer>();
  }

  protected CResultSet(final TDSMessage message, final Statement stmt, final String sql, final int resultSetType, final int resultSetConcurrency) throws SQLException {
    this(message, stmt);

    tdsResultSet = message.cursorOpen(sql, resultSetType, resultSetConcurrency);
    lastRow.set(message.cursorRows());

    if (fetchSize == 0) {
      fetchSize = Integer.MAX_VALUE;
    }
  }

  @Override
  protected void finalize() throws Throwable {
    super.finalize();
    close();
  }

  public void close() throws SQLException {
    if (tdsResultSet != null) {
      int c = tdsResultSet.getCursor();
      if (c != 0) {
        if (lock != null) {
          try {
            lock.lock();
            message.cursorClose(c);
          } finally {
            lock.unlock();
          }
        } else {
          message.cursorClose(c);
        }
      }
      tdsResultSet = null;
    }
  }

  public boolean isClosed() throws SQLException {
    return tdsResultSet == null;
  }

  protected final void initUpdateValue() {
    updateValues = new UpdateValue[tdsResultSet.columnCount()];
    for (int i = 0; i < updateValues.length; i++) {
      updateValues[i] = new UpdateValue(tdsResultSet.getColumnName(i), tdsResultSet.getColumnInfo(i));
    }
  }

  public int getInt(int columnIndex) throws SQLException {
    lastColumnIndex = columnIndex - 1;
    final Integer ret = tdsResultSet.getInt(rsIndex, lastColumnIndex);
    return ret;
  }

  public String getString(int columnIndex) throws SQLException {
    lastColumnIndex = columnIndex - 1;
    final String ret = tdsResultSet.getString(rsIndex, lastColumnIndex);
    return ret;
  }

  public double getDouble(int columnIndex) throws SQLException {
    lastColumnIndex = columnIndex - 1;
    final Double ret = tdsResultSet.getDouble(rsIndex, lastColumnIndex);
    return ret;
  }

  public Date getDate(int columnIndex) throws SQLException {
    lastColumnIndex = columnIndex - 1;
    final Date ret = tdsResultSet.getDate(rsIndex, lastColumnIndex);
    return ret;
  }

  public int getRow() throws SQLException {
    /* If there's no current row return 0. */
    if (currentRow == ROW_BEFORE || currentRow == ROW_AFTER || currentRow == ROW_INSERT || (lastRow.get() > 0 && currentRow > lastRow.get())) {
      return 0;
    }
    return currentRow;
  }

  public boolean wasNull() throws SQLException {
    return tdsResultSet.wasNull(rsIndex, lastColumnIndex);
  }

  // <editor-fold defaultstate="collapsed" desc="Row fetch methods.">
  public void refreshRow() throws SQLException {
    tdsResultSet = message.cursorFetch(tdsResultSet.getCursor(), SP_CURSORFETCH_FETCHTYPE_REFRESH, 0, 0); // the last two parameters are ignored by the REFRESH fetch.
  }

  @Override
  public boolean next() throws SQLException {
    ResultSetScroll next = new ResultSetScroll() {

      public void calcCurrentRow() {
        ++currentRow;
      }

      public void calcRSIndex() {
        ++rsIndex;
      }

      public void resetCache() {
        rsIndex = 0;
        forwardCache();
      }

      public void fetch() throws SQLException {
        tdsResultSet = message.cursorFetch(tdsResultSet.getCursor(), SP_CURSORFETCH_FETCHTYPE_NEXT, currentRow, fetchSize);
      }
    };
    return scroll(next);
  }

  @Override
  public boolean previous() throws SQLException {
    ResultSetScroll previous = new ResultSetScroll() {

      public void calcCurrentRow() {
        --currentRow;
      }

      public void calcRSIndex() {
        --rsIndex;
      }

      public void resetCache() throws SQLException {
        rsIndex = tdsResultSet.rowCount() - 1;
        backwardCache();
      }

      public void fetch() throws SQLException {
        tdsResultSet = message.cursorFetch(tdsResultSet.getCursor(), SP_CURSORFETCH_FETCHTYPE_PREV_NOADJUST, currentRow, fetchSize);
      }
    };
    return scroll(previous);
  }

  @Override
  public boolean absolute(final int row) throws SQLException {
    if (row < 1) {
      if (row == 0) {
        beforeFirst();
        return false;
      }
      int absRow = Math.abs(row);
      if (absRow > lastRow.get()) {
        return false;
      }
      afterLast();
      return absolute((lastRow.get() + 1) - absRow);
    }
    if (row > lastRow.get()) {
      afterLast();
      return false;
    }

    ResultSetScroll absolute = new ResultSetScroll() {

      private int oldRow = currentRow;

      public void calcCurrentRow() {
        currentRow = row;
      }

      public void calcRSIndex() {
        rsIndex += (row - oldRow);
      }

      public void resetCache() {
        rsIndex = 0;
        forwardCache();
      }

      public void fetch() throws SQLException {
        tdsResultSet = message.cursorFetch(tdsResultSet.getCursor(), SP_CURSORFETCH_FETCHTYPE_ABSOLUTE, currentRow, fetchSize);
      }
    };
    return scroll(absolute);
  }

  @Override
  public boolean relative(final int rows) throws SQLException {
    ResultSetScroll relative = new ResultSetScroll() {

      public void calcCurrentRow() {
        currentRow += rows;
      }

      public void calcRSIndex() {
        rsIndex += rows;
      }

      public void resetCache() {
        rsIndex = 0;
        forwardCache();
      }

      public void fetch() throws SQLException {
        tdsResultSet = message.cursorFetch(tdsResultSet.getCursor(), SP_CURSORFETCH_FETCHTYPE_ABSOLUTE, currentRow, fetchSize);
      }
    };
    return scroll(relative);
  }

  @Override
  public boolean first() throws SQLException {
    ResultSetScroll last = new ResultSetScroll() {

      public void calcCurrentRow() throws SQLException {
        currentRow = 1;
      }

      public void calcRSIndex() {
        rsIndex = 0;
      }

      public void resetCache() {
        rsIndex = 0;
        forwardCache();
      }

      public void fetch() throws SQLException {
        tdsResultSet = message.cursorFetch(tdsResultSet.getCursor(), SP_CURSORFETCH_FETCHTYPE_FIRST, currentRow, fetchSize);
      }
    };
    return scroll(last);
  }

  @Override
  public boolean last() throws SQLException {
    ResultSetScroll last = new ResultSetScroll() {

      public void calcCurrentRow() throws SQLException {
        currentRow = lastRow.get();
      }

      public void calcRSIndex() {
        rsIndex = tdsResultSet.rowCount() - 1;
      }

      public void resetCache() throws SQLException {
        rsIndex = tdsResultSet.rowCount() - 1;
        backwardCache();
      }

      public void fetch() throws SQLException {
        tdsResultSet = message.cursorFetch(tdsResultSet.getCursor(), SP_CURSORFETCH_FETCHTYPE_LAST, currentRow, fetchSize);
      }
    };
    return scroll(last);
  }

  @Override
  public void afterLast() throws SQLException {
    ResultSetScroll afterLast = new ResultSetScroll() {

      public void calcCurrentRow() throws SQLException {
        currentRow = (lastRow.get() + 1);
        cacheBegining = cacheEnd = 0;
        tdsResultSet = message.cursorFetch(tdsResultSet.getCursor(), SP_CURSORFETCH_FETCHTYPE_LAST, currentRow, 0);
      }

      public void calcRSIndex() {
      }

      public void resetCache() {
      }

      public void fetch() throws SQLException {
      }
    };
    scroll(afterLast);
  }

  @Override
  public void beforeFirst() throws SQLException {
    ResultSetScroll beforeFirst = new ResultSetScroll() {

      public void calcCurrentRow() throws SQLException {
        currentRow = ROW_BEFORE;
        cacheBegining = cacheEnd = 0;
        // fetch must be done here because scroll will never call fetch()
        tdsResultSet = message.cursorFetch(tdsResultSet.getCursor(), SP_CURSORFETCH_FETCHTYPE_FIRST, currentRow, 0);
      }

      public void calcRSIndex() {
        rsIndex = -1;
      }

      public void resetCache() {
        cacheBegining = cacheEnd = 0;
      }

      public void fetch() throws SQLException {
        // fetch is call during calcCurrentRow()
      }
    };
    scroll(beforeFirst);
  }

  @Override
  public boolean isAfterLast() throws SQLException {
    return currentRow == (lastRow.get() + 1);
  }

  @Override
  public boolean isBeforeFirst() throws SQLException {
    return currentRow == ROW_BEFORE;
  }

  @Override
  public boolean isFirst() throws SQLException {
    return currentRow == 1;
  }

  @Override
  public boolean isLast() throws SQLException {
    return currentRow == lastRow.get();
  }
  // </editor-fold>

  // <editor-fold defaultstate="collapsed" desc="Update, Insert & Delete">
  public void cancelRowUpdates() throws SQLException {
    for (int i = 0; i < updateValues.length; i++) {
      updateValues[i].clear();
    }
  }

  public void moveToCurrentRow() throws SQLException {
    /* This method has no effect if the cursor is not on the insert row. */
    if (currentRow == ROW_INSERT) {
      currentRow = rowBackup;
    }
  }

  public void moveToInsertRow() throws SQLException {
    rowBackup = currentRow;
    currentRow = ROW_INSERT;
  }

  public void updateInt(int columnIndex, int x) throws SQLException {
    updateValues[columnIndex - 1].setValue(x);
  }

  public void updateString(int columnIndex, String x) throws SQLException {
    updateValues[columnIndex - 1].setValue(x);
  }

  public void updateDouble(int columnIndex, double x) throws SQLException {
    updateValues[columnIndex - 1].setValue(x);
  }

  public void updateDate(int columnIndex, Date x) throws SQLException {
    updateValues[columnIndex - 1].setValue(x);
  }

  public void insertRow() throws SQLException {
    checkInsertRow();

    message.cursorInsert(tdsResultSet.getCursor(), updateValues);
    lastRow.incrementAndGet();
    cancelRowUpdates();
  }

  public void updateRow() throws SQLException {
    message.cursorUpdate(tdsResultSet.getCursor(), rsIndex + 1, updateValues);
    /* Update cache with new values. */
    tdsResultSet.updateRow(rsIndex, updateValues);
    cancelRowUpdates();
  }

  public void deleteRow() throws SQLException {
    if (currentRow == ROW_INSERT) {
      throw new SQLException(Messages.msg_is_on_insert_row);
    }
    message.cursorDelete(tdsResultSet.getCursor(), rsIndex + 1);
    deletedRows.add(currentRow);
  }

  public boolean rowDeleted() throws SQLException {
    return deletedRows.contains(currentRow);
  }
  // </editor-fold>

  public void setFetchDirection(int direction) throws SQLException {
    fetchDirection = direction;
  }

  public int getFetchDirection() throws SQLException {
    return fetchDirection;
  }

  public void setFetchSize(int rows) throws SQLException {
    if (rows < 0) {
      throw new SQLException("'rows' must be greater or equal than zero (>= 0).");
    }
    if (rows == 0) {
      fetchSize = Integer.MAX_VALUE;
    } else {
      fetchSize = rows;
    }
  }

  public int getFetchSize() throws SQLException {
    return fetchSize;
  }

  public int getType() throws SQLException {
    return stmt.getResultSetType();
  }

  public int getConcurrency() throws SQLException {
    return stmt.getResultSetConcurrency();
  }

  public Statement getStatement() throws SQLException {
    return stmt;
  }

  /**
   * Get the TDS result set.
   *
   * @return TDS result set object.
   */
  public final ITDSResultSet getTDSResultSet() {
    return tdsResultSet;
  }

  /**
   * Check if the current row is in cache.
   *
   * @return {@code true} if currentRow is in cache, otherwise {@code false}.
   */
  protected final boolean inCache() {
    return (currentRow >= cacheBegining) && (currentRow < cacheEnd);
  }

  /**
   * Calculate the new cache boundaries when moving forward.
   */
  protected final void forwardCache() {
    cacheBegining = currentRow;
    cacheEnd = cacheBegining + tdsResultSet.rowCount();
  }

  /**
   * Calculate the new cache boundaries when moving backwards.
   */
  protected final void backwardCache() {
    cacheEnd = currentRow + 1;
    if (cacheEnd > fetchSize) {
      cacheBegining = cacheEnd - fetchSize;
    } else {
      cacheBegining = 1;
    }
  }

  /**
   * Check if result set if on insert row.
   *
   * @throws SQLException if it's not.
   */
  protected final void checkInsertRow() throws SQLException {
    if (currentRow != ROW_INSERT) {
      cancelRowUpdates();
      throw new SQLException(Messages.msg_is_not_on_insert_row);
    }
  }

  /**
   * Scroll the result set.
   *
   * @param impl result set scroll implementation.
   *
   * @return {@code true} if the result set is in a row, otherwise {@code false}.
   *
   * @throws SQLException if an i/o error occurs while reading the result set from the input stream.
   */
  protected boolean scroll(final ResultSetScroll impl) throws SQLException {
    impl.calcCurrentRow();
    if (currentRow < 1) {
      currentRow = ROW_BEFORE;
      rsIndex = -1;
      return false;
    }
    if (currentRow > lastRow.get()) {
      currentRow = (lastRow.get() + 1);
      rsIndex = tdsResultSet.rowCount();
      return false;
    }
    if (tdsResultSet.isEmpty() || !inCache()) {
      impl.fetch();
      impl.resetCache();
    } else {
      impl.calcRSIndex();
    }
    return true;
  }

  // <editor-fold defaultstate="collapsed" desc="Not implemented">
  public boolean getBoolean(int columnIndex) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public byte getByte(int columnIndex) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public short getShort(int columnIndex) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public long getLong(int columnIndex) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public float getFloat(int columnIndex) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public byte[] getBytes(int columnIndex) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public Time getTime(int columnIndex) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public Timestamp getTimestamp(int columnIndex) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public InputStream getAsciiStream(int columnIndex) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public InputStream getUnicodeStream(int columnIndex) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public InputStream getBinaryStream(int columnIndex) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public String getString(String columnLabel) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public boolean getBoolean(String columnLabel) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public byte getByte(String columnLabel) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public short getShort(String columnLabel) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public int getInt(String columnLabel) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public long getLong(String columnLabel) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public float getFloat(String columnLabel) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public double getDouble(String columnLabel) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public byte[] getBytes(String columnLabel) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public Date getDate(String columnLabel) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public Time getTime(String columnLabel) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public Timestamp getTimestamp(String columnLabel) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public InputStream getAsciiStream(String columnLabel) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public InputStream getUnicodeStream(String columnLabel) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public InputStream getBinaryStream(String columnLabel) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public SQLWarning getWarnings() throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void clearWarnings() throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public String getCursorName() throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public ResultSetMetaData getMetaData() throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public Object getObject(int columnIndex) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public Object getObject(String columnLabel) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public int findColumn(String columnLabel) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public Reader getCharacterStream(int columnIndex) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public Reader getCharacterStream(String columnLabel) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public BigDecimal getBigDecimal(String columnLabel) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public boolean rowUpdated() throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public boolean rowInserted() throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateNull(int columnIndex) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateBoolean(int columnIndex, boolean x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateByte(int columnIndex, byte x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateShort(int columnIndex, short x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateLong(int columnIndex, long x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateFloat(int columnIndex, float x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateBytes(int columnIndex, byte[] x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateTime(int columnIndex, Time x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateTimestamp(int columnIndex, Timestamp x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateAsciiStream(int columnIndex, InputStream x, int length) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateBinaryStream(int columnIndex, InputStream x, int length) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateCharacterStream(int columnIndex, Reader x, int length) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateObject(int columnIndex, Object x, int scaleOrLength) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateObject(int columnIndex, Object x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateNull(String columnLabel) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateBoolean(String columnLabel, boolean x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateByte(String columnLabel, byte x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateShort(String columnLabel, short x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateInt(String columnLabel, int x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateLong(String columnLabel, long x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateFloat(String columnLabel, float x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateDouble(String columnLabel, double x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateBigDecimal(String columnLabel, BigDecimal x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateString(String columnLabel, String x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateBytes(String columnLabel, byte[] x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateDate(String columnLabel, Date x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateTime(String columnLabel, Time x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateTimestamp(String columnLabel, Timestamp x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateAsciiStream(String columnLabel, InputStream x, int length) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateBinaryStream(String columnLabel, InputStream x, int length) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateCharacterStream(String columnLabel, Reader reader, int length) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateObject(String columnLabel, Object x, int scaleOrLength) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateObject(String columnLabel, Object x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public Object getObject(int columnIndex, Map<String, Class<?>> map) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public Ref getRef(int columnIndex) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public Blob getBlob(int columnIndex) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public Clob getClob(int columnIndex) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public Array getArray(int columnIndex) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public Object getObject(String columnLabel, Map<String, Class<?>> map) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public Ref getRef(String columnLabel) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public Blob getBlob(String columnLabel) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public Clob getClob(String columnLabel) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public Array getArray(String columnLabel) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public Date getDate(int columnIndex, Calendar cal) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public Date getDate(String columnLabel, Calendar cal) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public Time getTime(int columnIndex, Calendar cal) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public Time getTime(String columnLabel, Calendar cal) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public Timestamp getTimestamp(String columnLabel, Calendar cal) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public URL getURL(int columnIndex) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public URL getURL(String columnLabel) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateRef(int columnIndex, Ref x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateRef(String columnLabel, Ref x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateBlob(int columnIndex, Blob x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateBlob(String columnLabel, Blob x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateClob(int columnIndex, Clob x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateClob(String columnLabel, Clob x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateArray(int columnIndex, Array x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateArray(String columnLabel, Array x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public RowId getRowId(int columnIndex) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public RowId getRowId(String columnLabel) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateRowId(int columnIndex, RowId x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateRowId(String columnLabel, RowId x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public int getHoldability() throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateNString(int columnIndex, String nString) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateNString(String columnLabel, String nString) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateNClob(int columnIndex, NClob nClob) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateNClob(String columnLabel, NClob nClob) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public NClob getNClob(int columnIndex) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public NClob getNClob(String columnLabel) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public SQLXML getSQLXML(int columnIndex) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public SQLXML getSQLXML(String columnLabel) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateSQLXML(String columnLabel, SQLXML xmlObject) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public String getNString(int columnIndex) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public String getNString(String columnLabel) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public Reader getNCharacterStream(int columnIndex) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public Reader getNCharacterStream(String columnLabel) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateNCharacterStream(int columnIndex, Reader x, long length) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateNCharacterStream(String columnLabel, Reader reader, long length) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateAsciiStream(int columnIndex, InputStream x, long length) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateBinaryStream(int columnIndex, InputStream x, long length) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateCharacterStream(int columnIndex, Reader x, long length) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateAsciiStream(String columnLabel, InputStream x, long length) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateBinaryStream(String columnLabel, InputStream x, long length) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateCharacterStream(String columnLabel, Reader reader, long length) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateClob(int columnIndex, Reader reader, long length) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateClob(String columnLabel, Reader reader, long length) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateNClob(int columnIndex, Reader reader, long length) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateNClob(String columnLabel, Reader reader, long length) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateNCharacterStream(int columnIndex, Reader x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateNCharacterStream(String columnLabel, Reader reader) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateAsciiStream(int columnIndex, InputStream x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateBinaryStream(int columnIndex, InputStream x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateCharacterStream(int columnIndex, Reader x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateAsciiStream(String columnLabel, InputStream x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateBinaryStream(String columnLabel, InputStream x) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateCharacterStream(String columnLabel, Reader reader) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateClob(int columnIndex, Reader reader) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateClob(String columnLabel, Reader reader) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateNClob(int columnIndex, Reader reader) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void updateNClob(String columnLabel, Reader reader) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public <T> T unwrap(Class<T> iface) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public boolean isWrapperFor(Class<?> iface) throws SQLException {
    throw new UnsupportedOperationException("Not supported yet.");
  }
  // </editor-fold>
}
